<?php
	/**
	  * @package	MyDebuger
	  * @name		MyLoader
	  * @brief		Clase para cargar ficheros de clases PHP
	  * @author		Hermann D. Schimpf <hschimpf@gschimpf.com>
	  * @license	http://opensource.org/licenses/gpl-2.0.php
	  * @date		2009-12-14
	  * @version	0.1.1
  	**/

	final class MyLoader extends MyDebuger implements MyVersions {
		/* version de la clase */
		private static $version			= 0;
		/* subversion de la clase */
		private static $subversion		= 1;
		/* numero de revision de la clase */
		private static $revision		= 1;

		/* nombre de las clases y direccion a sus ficheros */
		private $fileClasses			= Array();
		/* fichero de configuraciones */
		private $configFile			= False;
		/* bandera para saber si se cargaron los datos */
		private $datosCargados		= False;

		public function __construct($debug = False, $fileName = 'myloader.config') {
			/* creamos el padre */
			parent::__construct($debug, __CLASS__, 086);
			/* habilitamos el registro en un fichero */
			$this->enableLog(__CLASS__ . '.log');
			/* almacenamos el nombre del fichero */
			$this->configFile = $fileName;
			/* cargamos los datos */
			$this->loadDataFromFile();
		}

		public static final function getVersion() {
			/* retornamos la version actual de la clase */
			return 'v' . self::$version . '.' . self::$subversion . '.' . self::$revision;
		}

		public function loadClass($className = Null) {
			try {
				try {
					/* realizamos algunas verfificaciones */
					$this->verificarClaseImportar($className);
					/* agregamos el fichero de la clase */
					$this->loadClassFile($className);
				} catch (Exception $e) {
					/* capturamos todos los errores y los transformamos en mi excepcion */
					$this->convertToMyException($e);
				}
			} catch (MyException $e) {
				/* si se produjo una excepcion la manejamos con el metodo 'show' */
				$this->show($e->getMensaje());
			}
		}

		private function verificarClaseImportar($className) {
			/* verificamos si especifico un nombre de clase */
			if ($className === Null)
				/* salimos con una excepcion */
				$this->newException('No se especifico el nombre de la clase a cargar');
			/* verificamos si tenemos la clase */
			if (!array_key_exists($className, $this->fileClasses))
				/* salimos con una excepcion */
				$this->newException('La clase ' . $this->italic($className) . ' no existe');
		}

		private function loadClassFile($className) {
			/* mostramos un mensaje */
			$this->show('Loading class ' . $this->italic($this->blue($className)) . ' in ' . $this->italic($this->yellow($this->fileClasses[$className]['fileName'])) . '..');
		}

		private function loadDataFromFile() {
			try {
				try {
					/* verificamos que exista la clase necesaria */
					$this->verificarClase('MyTools');
					/* verificamos el archivo */
					$this->verificarFichero();
					/* cargamos los datos del fichero */
					$this->cargarDatosFichero();
					/* modificamos la bandera */
					$this->datosCargados = True;
				} catch (Exception $e) {
					/* capturamos todos los errores y los transformamos en mi excepcion */
					$this->convertToMyException($e);
				}
			} catch (MyException $e) {
				/* si se produjo una excepcion la manejamos con el metodo 'show' */
				$this->show($e->getMensaje());
			}
		}

		private function verificarFichero() {
			/* mostramos un mensaje */
			$this->show('Verificando fichero de configuraciones..', False);
			/* verificamos si el fichero existe */
			if (!file_exists($this->configFile))
				/* salimos con una excepcion */
				$this->newException('El fichero ' . $this->italic($this->configFile) . ' no existe');
			/* verificamos si podemos leer el fichero */
			if (!is_readable($this->configFile))
				/* salimos con una excepcion */
				$this->newException('No se tienen permisos de lectura sobre el fichero ' . $this->italic($this->configFile));
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function cargarDatosFichero() {
			/* mostramos un mensaje */
			$this->show('Cargando configuraciones desde el fichero ' . $this->italic($this->configFile) . '..', False);
			/* abrimos el fichero */
			$this->abrirFichero();
			/* limpiamos el contenido del fichero */
			$this->limpiarFichero();
			/* verificamos que el formato del fichero sea correcto */
			$this->verificarFormatoFichero();
			/* procesamos el fichero */
			$this->procesarFichero();
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function abrirFichero() {
			/* obtenemos los datos del fichero */
			$this->configFile = file_get_contents($this->configFile);
		}

		private function limpiarFichero() {
			/* eliminamos los comentarios del fichero */
			$this->configFile = preg_replace('/\/\*(.*?)\*\//si', '', $this->configFile);
		}

		private function verificarFormatoFichero() {
			/* verificamos si el formato del fichero es correcto */
			if (json_decode($this->configFile) === Null)
				/* salimos con una excepcion */
				$this->newException('El formato del fichero no es correcto');
		}

		private function procesarFichero() {
			/* obtenemos los datos del fichero */
			$this->obtenerDatosFichero();
			/* verificamos que el formato este correcto */
			$this->verificarFormatoArray();
			/* procesamos el fichero */
			$this->procesarDatosFichero();
		}

		private function obtenerDatosFichero() {
			/* obtenemos los datos del fichero */
			$this->configFile = json_decode($this->configFile);
			/* convertimos el objeto a array */
			$this->configFile = MyTools::ObjectToArray($this->configFile);
		}

		private function verificarFormatoArray() {
			/* recorremos el array obtenido */
			foreach ($this->configFile AS $class => $value) {
				/* verificamos si el tipo no es un array */
				if (gettype($class) === 'array')
					/* salimos con una excepcion */
					$this->newException('El formato del fichero no es correcto. Configuracion de la clase ' . $this->italic($class));
			}
		}

		private function procesarDatosFichero() {
			/* recorremos el array obtenido */
			foreach ($this->configFile AS $class => $path) {
				/* realizamos verificaciones del fichero */
				$this->verificarFicheroClase($path);
				/* verificamos si la clase existe en el fichero */
				$this->verificarClaseEnFichero($class, $path);
				/* almacenamos el nombre de la clase y el fichero */
				$this->guardarClaseFichero($class, $path);
			}
		}

		private function verificarFicheroClase($fileName) {
			/* verificamos si el fichero existe */
			if (!file_exists($fileName))
				/* salimos con una excepcion */
				$this->newException('El fichero ' . $this->italic($fileName) . ' no existe');
			/* verificamos si podemos leer el fichero */
			if (!is_readable($fileName))
				/* salimos con una excepcion */
				$this->newException('No se tienen permisos de lectura sobre el fichero ' . $this->italic($fileName));
		}

		private function verificarClaseEnFichero($class, $fileName) {
			/* verificamos si la clase esta definida en el fichero */
			if (!stristr(preg_replace('/\s\s+/', ' ', file_get_contents($fileName)), "class $class"))
				/* salimos con una excepcion */
				$this->newException('La clase ' . $this->italic($this->bold($class)) . ' no esta definida en el fichero ' . $this->italic($fileName));
		}

		private function guardarClaseFichero($class, $fileName) {
			/* agregamos un elemento al array con las clases */
			$this->fileClasses[$class]['fileName'] = $fileName;
		}
	}
?>
